package com.leon.datalink.core.persistence;

import com.leon.datalink.core.persistence.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 智能快照策略管理器
 * 
 * 根据不同Actor类型和运行状态，动态调整快照策略：
 * 1. 基于Actor优先级的快照频率
 * 2. 基于状态变化频率的动态调整
 * 3. 基于存储空间的压缩策略
 * 4. 基于恢复时间的优化策略
 * 
 * @author leon
 */
public class SnapshotStrategyManager {
    
    private static final Logger logger = LoggerFactory.getLogger(SnapshotStrategyManager.class);
    
    private static volatile SnapshotStrategyManager instance;
    
    // Actor快照策略缓存
    private final Map<String, SnapshotStrategy> actorStrategies = new ConcurrentHashMap<>();
    
    // Actor状态变化统计
    private final Map<String, StateChangeStats> stateChangeStats = new ConcurrentHashMap<>();
    
    private SnapshotStrategyManager() {
        initializeDefaultStrategies();
    }
    
    public static SnapshotStrategyManager getInstance() {
        if (instance == null) {
            synchronized (SnapshotStrategyManager.class) {
                if (instance == null) {
                    instance = new SnapshotStrategyManager();
                }
            }
        }
        return instance;
    }
    
    /**
     * 获取Actor的快照策略
     */
    public SnapshotStrategy getSnapshotStrategy(String actorClassName, String nodeId) {
        String key = actorClassName + ":" + nodeId;
        return actorStrategies.computeIfAbsent(key, k -> createSnapshotStrategy(actorClassName, nodeId));
    }
    
    /**
     * 更新状态变化统计
     */
    public void updateStateChangeStats(String actorClassName, String nodeId, NodeState oldState, NodeState newState) {
        String key = actorClassName + ":" + nodeId;
        StateChangeStats stats = stateChangeStats.computeIfAbsent(key, k -> new StateChangeStats());
        
        stats.recordStateChange(oldState, newState);
        
        // 动态调整快照策略
        adjustSnapshotStrategy(key, stats);
    }
    
    /**
     * 判断是否需要创建快照
     */
    public boolean shouldCreateSnapshot(String actorClassName, String nodeId, int eventCount, NodeState currentState) {
        SnapshotStrategy strategy = getSnapshotStrategy(actorClassName, nodeId);
        
        // 基于事件计数的判断
        if (eventCount >= strategy.getSnapshotFrequency()) {
            return true;
        }
        
        // 基于状态重要性的判断
        if (strategy.isImportantStateChange(currentState)) {
            return true;
        }
        
        // 基于时间间隔的判断
        long timeSinceLastSnapshot = System.currentTimeMillis() - strategy.getLastSnapshotTime();
        if (timeSinceLastSnapshot >= strategy.getMaxSnapshotInterval()) {
            return true;
        }
        
        return false;
    }
    
    /**
     * 记录快照创建
     */
    public void recordSnapshotCreated(String actorClassName, String nodeId, long snapshotSize) {
        SnapshotStrategy strategy = getSnapshotStrategy(actorClassName, nodeId);
        strategy.recordSnapshot(snapshotSize);
        
        logger.debug("Snapshot created for {}:{}, size: {}KB", actorClassName, nodeId, snapshotSize / 1024);
    }
    
    /**
     * 创建Actor特定的快照策略
     */
    private SnapshotStrategy createSnapshotStrategy(String actorClassName, String nodeId) {
        int priority = NodeActorStateAnalysis.getActorPersistencePriority(actorClassName);
        String simpleClassName = actorClassName.substring(actorClassName.lastIndexOf('.') + 1);
        
        SnapshotStrategy strategy = new SnapshotStrategy();
        strategy.setActorClassName(actorClassName);
        strategy.setNodeId(nodeId);
        strategy.setPriority(priority);
        
        // 根据Actor类型设置策略
        switch (simpleClassName) {
            case "RuleActor":
                strategy.setSnapshotFrequency(50);  // 更频繁的快照
                strategy.setMaxSnapshots(10);
                strategy.setMaxSnapshotInterval(30000); // 30秒
                break;
                
            case "ScheduleNodeActor":
                strategy.setSnapshotFrequency(100);
                strategy.setMaxSnapshots(5);
                strategy.setMaxSnapshotInterval(60000); // 1分钟
                break;
                
            case "DriverNodeActor":
                strategy.setSnapshotFrequency(500);
                strategy.setMaxSnapshots(3);
                strategy.setMaxSnapshotInterval(300000); // 5分钟
                break;
                
            case "SpeedNodeActor":
            case "PackNodeActor":
                strategy.setSnapshotFrequency(200);
                strategy.setMaxSnapshots(3);
                strategy.setMaxSnapshotInterval(120000); // 2分钟
                break;
                
            default:
                // 默认策略基于优先级
                strategy.setSnapshotFrequency(getDefaultFrequencyByPriority(priority));
                strategy.setMaxSnapshots(getDefaultMaxSnapshotsByPriority(priority));
                strategy.setMaxSnapshotInterval(getDefaultIntervalByPriority(priority));
        }
        
        logger.info("Created snapshot strategy for {}: freq={}, maxSnapshots={}, maxInterval={}ms",
                   simpleClassName, strategy.getSnapshotFrequency(), strategy.getMaxSnapshots(), 
                   strategy.getMaxSnapshotInterval());
        
        return strategy;
    }
    
    /**
     * 动态调整快照策略
     */
    private void adjustSnapshotStrategy(String key, StateChangeStats stats) {
        SnapshotStrategy strategy = actorStrategies.get(key);
        if (strategy == null) return;
        
        // 如果状态变化频繁，增加快照频率
        if (stats.getChangeRate() > 10.0) { // 每秒超过10次变化
            int newFrequency = Math.max(strategy.getSnapshotFrequency() / 2, 10);
            strategy.setSnapshotFrequency(newFrequency);
            logger.debug("Increased snapshot frequency for {} to {} due to high change rate", key, newFrequency);
        }
        // 如果状态变化很少，降低快照频率
        else if (stats.getChangeRate() < 0.1) { // 每秒少于0.1次变化
            int newFrequency = Math.min(strategy.getSnapshotFrequency() * 2, 2000);
            strategy.setSnapshotFrequency(newFrequency);
            logger.debug("Decreased snapshot frequency for {} to {} due to low change rate", key, newFrequency);
        }
    }
    
    /**
     * 初始化默认策略
     */
    private void initializeDefaultStrategies() {
        logger.info("Initializing default snapshot strategies");
    }
    
    private int getDefaultFrequencyByPriority(int priority) {
        switch (priority) {
            case 1: return 100;
            case 2: return 500;
            case 3: return 1000;
            default: return 2000;
        }
    }
    
    private int getDefaultMaxSnapshotsByPriority(int priority) {
        switch (priority) {
            case 1: return 5;
            case 2: return 3;
            case 3: return 2;
            default: return 1;
        }
    }
    
    private long getDefaultIntervalByPriority(int priority) {
        switch (priority) {
            case 1: return 60000;   // 1分钟
            case 2: return 300000;  // 5分钟
            case 3: return 600000;  // 10分钟
            default: return 1800000; // 30分钟
        }
    }
    
    /**
     * 快照策略类
     */
    public static class SnapshotStrategy {
        private String actorClassName;
        private String nodeId;
        private int priority;
        private int snapshotFrequency;
        private int maxSnapshots;
        private long maxSnapshotInterval;
        private long lastSnapshotTime = 0;
        private long totalSnapshotSize = 0;
        private int snapshotCount = 0;
        
        public boolean isImportantStateChange(NodeState state) {
            // 关键状态变化需要立即快照
            if (priority == 1) {
                return state.getStatus().name().contains("ERROR") || 
                       state.getStatus().name().contains("STOPPED");
            }
            return false;
        }
        
        public void recordSnapshot(long size) {
            lastSnapshotTime = System.currentTimeMillis();
            totalSnapshotSize += size;
            snapshotCount++;
        }
        
        public long getAverageSnapshotSize() {
            return snapshotCount > 0 ? totalSnapshotSize / snapshotCount : 0;
        }
        
        // Getters and Setters
        public String getActorClassName() { return actorClassName; }
        public void setActorClassName(String actorClassName) { this.actorClassName = actorClassName; }
        public String getNodeId() { return nodeId; }
        public void setNodeId(String nodeId) { this.nodeId = nodeId; }
        public int getPriority() { return priority; }
        public void setPriority(int priority) { this.priority = priority; }
        public int getSnapshotFrequency() { return snapshotFrequency; }
        public void setSnapshotFrequency(int snapshotFrequency) { this.snapshotFrequency = snapshotFrequency; }
        public int getMaxSnapshots() { return maxSnapshots; }
        public void setMaxSnapshots(int maxSnapshots) { this.maxSnapshots = maxSnapshots; }
        public long getMaxSnapshotInterval() { return maxSnapshotInterval; }
        public void setMaxSnapshotInterval(long maxSnapshotInterval) { this.maxSnapshotInterval = maxSnapshotInterval; }
        public long getLastSnapshotTime() { return lastSnapshotTime; }
        public long getTotalSnapshotSize() { return totalSnapshotSize; }
        public int getSnapshotCount() { return snapshotCount; }
    }
    
    /**
     * 状态变化统计类
     */
    public static class StateChangeStats {
        private long totalChanges = 0;
        private long startTime = System.currentTimeMillis();
        private long lastChangeTime = startTime;
        
        public void recordStateChange(NodeState oldState, NodeState newState) {
            totalChanges++;
            lastChangeTime = System.currentTimeMillis();
        }
        
        public double getChangeRate() {
            long duration = lastChangeTime - startTime;
            return duration > 0 ? (double) totalChanges * 1000 / duration : 0;
        }
        
        public long getTotalChanges() { return totalChanges; }
        public long getStartTime() { return startTime; }
        public long getLastChangeTime() { return lastChangeTime; }
    }

    /**
     * 获取平均快照频率
     */
    public double getAverageSnapshotFrequency() {
        // 计算所有Actor的平均快照频率
        if (actorStrategies.isEmpty()) {
            return 100.0; // 默认频率
        }

        double totalFrequency = 0.0;
        for (SnapshotStrategy strategy : actorStrategies.values()) {
            totalFrequency += strategy.getSnapshotFrequency();
        }

        return totalFrequency / actorStrategies.size();
    }

    /**
     * 更新Actor类型的快照策略
     */
    public void updateActorTypeStrategy(String actorType, int frequency) {
        SnapshotStrategy strategy = actorStrategies.get(actorType);
        if (strategy == null) {
            strategy = new SnapshotStrategy();
            strategy.setSnapshotFrequency(frequency);
            strategy.setMaxSnapshots(10);
            strategy.setMaxSnapshotInterval(1000);
            actorStrategies.put(actorType, strategy);
        } else {
            strategy.setSnapshotFrequency(frequency);
        }
        logger.info("Updated snapshot strategy for {}: frequency={}", actorType, frequency);
    }
}
